/*
 * PriorityQueueScheduler.cc
 *
 *  Created on: 2011-05-04
 *      Author: Piotrek
 */

#include "PriorityQueueScheduler.h"

Define_Module(PriorityQueueScheduler)

void PriorityQueueScheduler::initialize()
{
	AbstractScheduler::initialize();
	maxQueueSize = par("maxQueueSize");

	WATCH_MAP(queues);
}

PriorityQueueScheduler::~PriorityQueueScheduler()
{
	std::map<int32_t, cPacketQueue*, PriorityComparator>::iterator it;
	for(it = queues.begin(); it != queues.end(); it++)
	{
		it->second->clear();
		delete it->second;
	}

	queues.clear();
}

bool PriorityQueueScheduler::receivePacket(NetPacket* packet, int gateNum)
{
	if(canReceive(packet->getPriority()))
	{
		std::map<int32_t, cPacketQueue*, PriorityComparator>::iterator it;
		it = queues.find(packet->getPriority());
		if(it != queues.end())
		{
			cPacketQueue* queue = it->second;
			queue->insert(packet);
		}
		else
		{
			cPacketQueue* queue = new cPacketQueue();
			queue->setTakeOwnership(true);
			queue->insert(packet);

			queues.insert(std::pair<int32_t, cPacketQueue*>(packet->getPriority(), queue));
		}

		return true;
	}
	else
		return false;
}

bool PriorityQueueScheduler::hasPacketsAwaitingDeparture()
{
	std::map<int32_t, cPacketQueue*, PriorityComparator>::iterator it;
	for(it = queues.begin(); it != queues.end(); it++)
		if(!it->second->empty())
			return true;

	return false;
}

NetPacket* PriorityQueueScheduler::getPacketForDeparture()
{
	std::map<int32_t, cPacketQueue*, PriorityComparator>::iterator it;
	for(it = queues.begin(); it != queues.end(); it++)
	{
		cPacketQueue* queue = it->second;

		if(!queue->empty())
			return check_and_cast<NetPacket*>(queue->pop());
	}

	return NULL;
}

bool PriorityQueueScheduler::canReceive(int32_t queueNum)
{
	if(!maxQueueSize)
		return true;
	else
	{
		std::map<int32_t, cPacketQueue*, PriorityComparator>::iterator it;
		it = queues.find(queueNum);

		return it == queues.end() || it->second->getLength() < maxQueueSize;
	}
}
